﻿// owner 蒋家伟

#pragma once
#include <type_traits>
#include "DataPropertyDefine.h"
#include "DataSchemaChecked.h"
#include "DBVector.h"
#include "DBSet.h"
#include "DBMap.h"
#include "DBUMap.h"

namespace jsdk
{
    class IDocument;
    class IElement;
}

// 特别注意    : 所有宏如果希望放入的类别是自定义的继承于DBSchemaObject，必须使用 OwnerPtr<自定义类别> 包装一层，保证对象的所有权
// 可以为自定义的类别的接口类型 (只要传入的实现类别是继承DBSchemaObject，接口类别可以不需要继承DBSchemaObject)， 满足继承关联， 参照ObjectClassDefine.h 中 接口类型: ITestA, 实现类别分别为TestA1, TestA2

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的单个对象需要支持序列化使用
// 参数描述    : TYPENAME 类型， VALUENAME 变量名称
#define DATA(TYPENAME, VALUENAME) \
static_assert(jsdk::is_OwnerPtr<TYPENAME>::value || (jsdk::is_base_type<TYPENAME>::value) , "当前不支持该数据结构定义"); \
DATA_PROPERTY(TYPENAME, VALUENAME, jsdk::is_base_type<TYPENAME>::value);

// 宏描述      : 临时变量，不支持序列化。只指针存放文档指针与所属element对象
// 参数描述    : TYPENAME 类型， VALUENAME 变量名称
#define DATA_CUSTOM(TYPENAME, VALUENAME) \
static_assert(std::is_same<IElement*, TYPENAME>::value || std::is_same<IDocument*, TYPENAME>::value, "临时对象暂时只支持IElmenet与IIDocument指针"); \
DATA_POINTER_PROPERTY_CUSTOM(TYPENAME, VALUENAME)

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的数组对象需要支持序列化使用【Vector】
// 参数描述    : VALUE_TYPE 值类型， VALUENAME 变量名称
#define DATA_ARRAY(VALUE_TYPE, VALUENAME)\
static_assert(jsdk::is_OwnerPtr<VALUE_TYPE>::value || (jsdk::is_base_type<VALUE_TYPE>::value) , "当前不支持该数据结构定义"); \
CONTAINER_DATA_PROPERTY(jsdk::DBvector<VALUE_TYPE>, VALUENAME, jsdk::is_base_type<VALUE_TYPE>::value);

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的集合对象需要支持序列化使用【Set】
// 参数描述    : VALUE_TYPE 值类型， VALUENAME 变量名称
#define DATA_SET(VALUE_TYPE, VALUENAME)\
static_assert(jsdk::is_OwnerPtr<VALUE_TYPE>::value || (jsdk::is_base_type<VALUE_TYPE>::value) , "当前不支持该数据结构定义"); \
CONTAINER_DATA_PROPERTY(jsdk::DBSet< VALUE_TYPE >, VALUENAME, jsdk::is_base_type<VALUE_TYPE>::value);

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的集合对象需要支持序列化使用【Set】，当需要自定义比较器时使用
// 参数描述    : VALUE_TYPE 值类型，COMPARATOR比较器类型， VALUENAME 变量名称
#define DATA_SET_WITH_COMPARATOR(VALUE_TYPE,COMPARATOR, VALUENAME)\
static_assert(jsdk::is_OwnerPtr<VALUE_TYPE>::value || (jsdk::is_base_type<VALUE_TYPE>::value) , "当前不支持该数据结构定义"); \
CONTAINER_DATA_PROPERTY( REFELECT_JOIN_SET(VALUE_TYPE, COMPARATOR) , VALUENAME, jsdk::is_base_type<VALUE_TYPE>::value);

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的映射表对象需要支持序列化使用【Map】
// 参数描述    : KEY_TYPE 键值类型， VALUE_TYPE值类型, VALUENAME 变量名称
// 特别注意    : KEY_TYPE 只能为基本类型
#define DATA_MAP(KEY_TYPE, VALUE_TYPE, VALUENAME)\
static_assert(jsdk::is_base_type<KEY_TYPE>::value, "键值只能为基本类型"); \
static_assert(jsdk::is_OwnerPtr<VALUE_TYPE>::value || (jsdk::is_base_type<VALUE_TYPE>::value) , "当前不支持该数据结构定义"); \
CONTAINER_DATA_PROPERTY( REFELECT_JOIN_MAP(KEY_TYPE, VALUE_TYPE), VALUENAME, jsdk::is_base_type<VALUE_TYPE>::value);

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的映射表对象需要支持序列化使用【Map】，当需要自定义比较器时使用
// 参数描述    : KEY_TYPE 键值类型， VALUE_TYPE值类型, VALUENAME 变量名称
// 特别注意    : KEY_TYPE 只能为基本类型
#define DATA_MAP_WITH_COMPARATOR(KEY_TYPE, VALUE_TYPE, COMPARATOR, VALUENAME)\
static_assert(jsdk::is_base_type<KEY_TYPE>::value, "键值只能为基本类型"); \
static_assert(jsdk::is_OwnerPtr<VALUE_TYPE>::value || (jsdk::is_base_type<VALUE_TYPE>::value) , "当前不支持该数据结构定义"); \
CONTAINER_DATA_PROPERTY( REFELECT_JOIN_MAP_WITH_COMPARATOR(KEY_TYPE, VALUE_TYPE, COMPARATOR) , VALUENAME, jsdk::is_base_type<VALUE_TYPE>::value);

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的映射表对象需要支持序列化使用【Unorder_Map】
// 参数描述    : KEY_TYPE 键值类型， VALUE_TYPE值类型, VALUENAME 变量名称
// 特别注意    : KEY_TYPE 只能为基本类型
#define DATA_UMAP(KEY_TYPE, VALUE_TYPE, VALUENAME)\
static_assert(jsdk::is_base_type<KEY_TYPE>::value, "键值只能为基本类型"); \
static_assert(jsdk::is_OwnerPtr<VALUE_TYPE>::value || (jsdk::is_base_type<VALUE_TYPE>::value) , "当前不支持该数据结构定义"); \
CONTAINER_DATA_PROPERTY( REFELECT_JOIN_UMAP(KEY_TYPE, VALUE_TYPE), VALUENAME, jsdk::is_base_type<VALUE_TYPE>::value);

// 宏描述      : 当一个基本类型或者继承于DBSchemaObject的映射表对象需要支持序列化使用【Unorder_Map】，当需要自定义哈希函数
// 参数描述    : KEY_TYPE 键值类型， VALUE_TYPE值类型, VALUENAME 变量名称
// 特别注意    : KEY_TYPE 只能为基本类型
#define DATA_UMAP_WITH_HASHCACULATE(KEY_TYPE, VALUE_TYPE, HASHCACULATE, VALUENAME)\
static_assert(jsdk::is_base_type<KEY_TYPE>::value, "键值只能为基本类型"); \
static_assert(jsdk::is_OwnerPtr<VALUE_TYPE>::value || (jsdk::is_base_type<VALUE_TYPE>::value) , "当前不支持该数据结构定义"); \
CONTAINER_DATA_PROPERTY( REFELECT_JOIN_UMAP_WITH_HASHCACULATE(KEY_TYPE, VALUE_TYPE, HASHCACULATE) , VALUENAME, jsdk::is_base_type<VALUE_TYPE>::value);
